home *** CD-ROM | disk | FTP | other *** search
- /*==================================================================
- File: MacZStringExtractTool.cpp
-
- Contains: Tool for extracting ZString information from
- a binary on the Mac.
-
- Written by: Eric Traut
-
- Copyright: 2000-2001 Connectix Corporation
-
- This source has been placed into the public domain by
- Connectix Corporation. You have the right to modify,
- distribute or use this code without any legal limitations
- or finanicial/licensing requirements. Connectix is not
- liable for any problems that result from the use of this
- code.
-
- If you have comments, feedback, questions, or would like
- to submit bug fixes or updates to this code, please email
- opensource@connectix.com.
- ==================================================================*/
-
- #include "ZStringTool.h"
-
- #include <cstring>
- #include <cstddef>
- #include <cstdlib>
- #include <new>
-
- #include <Files.h>
- #include <Devices.h>
- #include <StandardFile.h>
- #include <Resources.h>
-
- #include "MacZString.h"
-
- extern "C" {
- #include <FSp_fopen.h>
- }
-
- static Boolean
- ReadBinaryImage(
- const FSSpec & inFileSpec,
- char * & outMemoryImage,
- UInt32 & outLength);
-
-
- /*------------------------------------------------------------------
- main
-
- Application main entry point.
- ------------------------------------------------------------------*/
-
- int
- main()
- {
- StandardFileReply sfReply;
- FSSpec newMacFileSpec;
- FSSpec oldMacFileSpec;
- FILE * reportFile = NULL;
- char * newBinaryImage;
- UInt32 newBinarySize;
- char * oldBinaryImage = NULL;
- UInt32 oldBinarySize;
- OSType typeList[4];
- Boolean userSuppliedOldSpec = false;
-
- // Initialize the Mac toolbox by printing to the SIOUX log.
- std::printf("Welcome to the ZString tool\n");
-
- // Ask for the new file name.
- StandardGetFile(NULL, 0, typeList, &sfReply);
- if (!sfReply.sfGood)
- {
- std::printf("Operation cancelled\n");
- return 1;
- }
-
- newMacFileSpec = sfReply.sfFile;
-
- // Ask for the old file name.
- StandardGetFile(NULL, 0, typeList, &sfReply);
- if (sfReply.sfGood)
- {
- oldMacFileSpec = sfReply.sfFile;
- userSuppliedOldSpec = true;
- }
-
- // Ask for the name of the output file.
- StandardPutFile("\pName the output file:", "\pZOverride.html", &sfReply);
- if (!sfReply.sfGood)
- {
- std::printf("Operation cancelled\n");
- return 1;
- }
-
- reportFile = FSp_fopen(&sfReply.sfFile, "w");
-
- // Read in the two binaries.
- if (!ReadBinaryImage(newMacFileSpec, newBinaryImage, newBinarySize))
- {
- std::printf("Operation cancelled\n");
- return 1;
- }
-
- if (userSuppliedOldSpec)
- {
- if (!ReadBinaryImage(oldMacFileSpec, oldBinaryImage, oldBinarySize))
- {
- std::printf("Operation cancelled\n");
- return 1;
- }
- }
-
- // Process the data.
- ZStringTool stringTool;
- Z_Boolean reportOK;
- ZToolOptions toolOptions;
-
- stringTool.ProcessBinaries(newBinaryImage, newBinarySize, oldBinaryImage, oldBinarySize, toolOptions);
- reportOK = stringTool.PrintReport(reportFile, toolOptions);
-
- fclose(reportFile);
- delete [] newBinaryImage;
- delete [] oldBinaryImage;
-
- if (reportOK)
- std::printf("Operation completed successfully\n");
- }
-
-
- /*------------------------------------------------------------------
- ReadBinaryImage
- ------------------------------------------------------------------*/
-
- Boolean
- ReadBinaryImage(
- const FSSpec & inFileSpec,
- char * & outMemoryImage,
- UInt32 & outLength)
- {
- FSSpec theSpec = inFileSpec;
- OSErr err = noErr;
-
- // get the catalog info
- CInfoPBRec catInfo;
- {
- catInfo.hFileInfo.ioCompletion = NULL;
- catInfo.hFileInfo.ioVRefNum = inFileSpec.vRefNum;
- catInfo.hFileInfo.ioNamePtr = const_cast<StringPtr>(inFileSpec.name);
- catInfo.hFileInfo.ioFDirIndex = 0;
- catInfo.hFileInfo.ioDirID = inFileSpec.parID;
- err = ::PBGetCatInfoSync(&catInfo);
- }
- if (err != noErr)
- {
- std::fprintf(stderr, "Error reading catalog info (err == %d).\n", err);
- return false;
- }
-
- // Allocate total memory required for binary image
- // We allocate the combined logical lengths of both forks. Since
- // we won't be scanning the resource map or the override resources
- // this will actually be alittle more memory than we need.
- outMemoryImage = new (nothrow) char[catInfo.hFileInfo.ioFlLgLen + catInfo.hFileInfo.ioFlRLgLen];
- if (outMemoryImage == NULL)
- {
- std::fprintf(stderr, "Not enough memory to load file.\n");
- return false;
- }
-
- if (catInfo.hFileInfo.ioFlAttrib & ioDirMask)
- {
- std::fprintf(stderr, "Selected item is a directory.\n");
- return false;
- }
-
- // initalize read data
- Byte * outMemPtr = reinterpret_cast<Byte *>(outMemoryImage);
- outLength = 0;
-
- if (catInfo.hFileInfo.ioFlLgLen > 0) // data fork exists
- {
- SInt16 dfRefNum = -1;
-
- // open the data fork
- err = ::FSpOpenDF(&theSpec, fsRdPerm, &dfRefNum);
- if (err != noErr)
- {
- std::fprintf(stderr, "Error opening data fork (err == %d).\n", err);
- return false;
- }
-
- // seek the start of file (redundant)
- err = ::SetFPos(dfRefNum, fsFromStart, 0);
- if (err != noErr)
- {
- std::fprintf(stderr, "Error seeking start-of-file (err == %d).\n", err);
- return false;
- }
-
- // read the entire logical data fork
- long readLength = catInfo.hFileInfo.ioFlLgLen;
- err = ::FSRead(dfRefNum, &readLength, outMemPtr);
- if (err != noErr)
- {
- std::fprintf(stderr, "Error reading data fork (err == %d).\n", err);
- return false;
- }
- outMemPtr += readLength;
- outLength += readLength;
-
- // close the data fork
- ::FSClose(dfRefNum); // error is ignored
- }
-
- if (catInfo.hFileInfo.ioFlRLgLen > 0) // resource fork exists
- {
- // preserve original resource file
- SInt16 originalResFile = ::CurResFile();
- SInt16 rfRefNum = -1;
-
- // open resource fork
- rfRefNum = ::FSpOpenResFile(&theSpec, fsRdPerm);
- if ((err = ::ResError()) != noErr)
- {
- std::fprintf(stderr, "Error opening resource fork (err == %d).\n", err);
- return false;
- }
-
- // read resources
- UInt32 typeCount = ::Count1Types();
- for (UInt32 i = 1; i <= typeCount; i++) // loop through res types
- {
- ResType resType;
- ::Get1IndType(&resType, i);
-
- // Skip over override dictionary res types.
- if (resType != kZStringOverrideDictionaryResType)
- {
- UInt32 resCount = ::Count1Resources(resType);
- for (UInt32 i = 1; i <= resCount; i++) // loop through res count
- {
- // read resource
- Handle resHandle = ::Get1IndResource(resType, i);
- if (resHandle != NULL)
- {
- Size resSize = ::GetHandleSize(resHandle);
- ::BlockMoveData(*resHandle, outMemPtr, resSize);
- outMemPtr += resSize;
- outLength += resSize;
- ::ReleaseResource(resHandle);
- }
- }
- }
- }
-
- // close the resource fork
- ::CloseResFile(rfRefNum);
-
- // restore original resource file
- ::UseResFile(originalResFile);
- }
-
- return (err == noErr);
- }
-
-
-